/** @file

Copyright (c) 2006-2023, Kunlun BIOS, Kunlun Technology (Beijing) Co., Ltd.. All
Rights Reserved.

You may not reproduce, distribute, publish, display, perform, modify, adapt,
transmit, broadcast, present, recite, release, license or otherwise exploit
any part of this publication in any form, by any means, without the prior
written permission of Kunlun Technology (Beijing) Co., Ltd..

Module Name:


Abstract:


Revision History:

**/


#include <PiDxe.h>

#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
#include <Library/ArmGenericTimerCounterLib.h>
#include <Protocol/WatchdogTimer.h>
//#include <Library/PeiKlSetupVarRWLib.h>
#include <Library/ArmWatchdogLib.h>
#include <Library/GenericWatchdogLib.h>
//[jckuang-0020]
#include <Library/PostCodeLib.h>
#include "PostCode.h"
//[jckuang-0020]

/**
  Feed the watch dog.

**/
VOID
FeedWatchdog (
  VOID
)
{
    WatchdogWriteRefreshRegister(0);
}


/**
  This function sets the amount of time to wait before firing the watchdog
  timer to TimerPeriod 1s units.  If TimerPeriod is 0, then the watchdog
  timer is disabled.

  @param  TimerPeriod      The amount of time in 1s units to wait before
                           the watchdog timer is fired. If TimerPeriod is zero,
                           then the watchdog timer is disabled.

  @retval EFI_SUCCESS      The watchdog timer has been programmed to fire
                           in TimerPeriod 1s units.

**/
STATIC
EFI_STATUS
EFIAPI
WatchdogSetTimerPeriod (
  IN UINT64   TimerPeriod
  )
{
  UINTN       SystemCount;
  UINT64      mNumTimerTicks;

  // if TimerPeriod is 0, this is a request to stop the watchdog.
  if (TimerPeriod == 0) {
    WatchdogDisable ();
    return EFI_SUCCESS;
  }

  // Work out how many timer ticks will equate to TimerPeriod
  mNumTimerTicks = ArmGenericTimerGetTimerFreq () * TimerPeriod;
  mNumTimerTicks >>= 1;
  DEBUG((EFI_D_INFO, "TimerFreq:%lld,mNumTimerTicks:%llu. \n",ArmGenericTimerGetTimerFreq (),mNumTimerTicks));

  /* If the number of required ticks is greater than the max the watchdog's
     offset register (WOR) can hold, we need to manually compute and set
     the compare register (WCV) */
  if (mNumTimerTicks > MAX_UINT32) {
    /* We need to enable the watchdog *before* writing to the compare register,
       because enabling the watchdog causes an "explicit refresh", which
       clobbers the compare register (WCV). In order to make sure this doesn't
       trigger an interrupt, set the offset to max. */
    WatchdogWriteOffsetRegister (MAX_UINT32);
    WatchdogEnable ();
    SystemCount = ArmGenericTimerGetSystemCount ();
    WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks);
  } else {

    WatchdogWriteOffsetRegister ((UINT32)mNumTimerTicks);
    WatchdogEnable ();
  }


  return EFI_SUCCESS;
}

/**
  Enable the watch dog.

  @param[out]  BootTimeOut      a pointer to UINT16.

  @retval EFI_SUCCESS           The operation succeeds.

**/
EFI_STATUS
StartWatchdog(
  UINT8  Enable,
  UINT8  WatchdogTimeOut,
  UINT16 *BootTimeOut
)
{
  //EFI_STATUS                         Status;
  //SYSTEM_SETUP_CONFIGURATION        *SetupVar;
  //WATCHDOG_CONFIG                   *pWatchdogData;
  UINT16                             TimeOut;

  TimeOut = 0;
  //SetupVar = NULL;
  //Status = PeiKlSetupVarRead(&SetupVar);
  //if(EFI_ERROR(Status)){
  //    return Status;
  //}
  //pWatchdogData = &SetupVar->watchdog;
  if(Enable==1){
    //[jckuang-0020]
    POST_CODE_EX(EFI_PROGRESS_CODE, PEI_WATCHDOG_INIT);
    //[jckuang-0020]
    DEBUG((EFI_D_INFO, "enable the Watchdog Timer. \n"));
    //[gliu-0023]add-start
    TimeOut = TIME_OUT_30S * (WatchdogTimeOut+1);
    //[gliu-0023]add-end
    DEBUG((EFI_D_INFO, "BIOS: In StartWatchdog(), line %d. TimeOut=%d\n", __LINE__,TimeOut));
    *BootTimeOut = TimeOut;
    //
    //WatchdogTimerDxe
    //
    //enable the Watchdog Timer.
    WatchdogSetTimerPeriod (TimeOut);

  }

  return EFI_SUCCESS;
}

/**
  Disable the watch dog.

**/
VOID
StopWatchdog(
  IN VOID
)
{

    WatchdogSetTimerPeriod (0x0000);
}

